#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<sys/epoll.h>
#include<ctype.h>
#include<arpa/inet.h>
#include<fcntl.h>
#include<unistd.h>
#define SERVICEPORT 9527
#define OPEN_SIZE 1024
void sys_error(const char*s){
      perror(s);
      exit(-1);
}
int main(){
   int listenfd;
   listenfd=socket(AF_INET,SOCK_STREAM,0);//创建套接字
   if(listenfd==-1){
      sys_error("socket is error");
   }
   //绑定地址结构
   struct sockaddr_in saddr,caddr;
   saddr.sin_port=htons(SERVICEPORT);
   saddr.sin_addr.s_addr=htonl(INADDR_ANY);
   saddr.sin_family=AF_INET;
   bind(listenfd,(struct sockaddr*)&saddr,sizeof(saddr));
   //监听
   listen(listenfd,128);
   //epoll实现IO多路复用
   int epfd,nums,i,connfd,caddr_len,sockfd,n,j;
   char buf[1024];//创建缓冲区
   struct epoll_event tempevent,ArrEvents[OPEN_SIZE];
   tempevent.events=EPOLLIN | EPOLLET; //设置为ET模式
   tempevent.data.fd=listenfd;
   epfd= epoll_create(OPEN_SIZE);//创建红黑树
   if(epfd==-1){
      sys_error("epoll_create is error");
   }
   //将节点添加到红黑树上
   int ret=epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&tempevent);
   if(ret==-1){
      sys_error("epoll_ctl is error");
   }

   //将通信文件描述符设置为非阻塞模式
   int flg=fcntl(listenfd,F_GETFL);
   flg|=O_NONBLOCK;
   fcntl(listenfd,F_SETFL,flg);
   //fcntl(listenfd,FGSETFL,O_NONBLOCK);
   while(1){
      //阻塞监听
      nums=epoll_wait(epfd,ArrEvents,OPEN_SIZE,-1);
      if(nums<0){
         sys_error("epoll_wait is error");
      }
      for(i=0;i<nums;i++){
         if(!(ArrEvents[i].events & EPOLLIN)){//如果不是读事件继续循环
           continue;
	 }
         if(ArrEvents[i].data.fd==listenfd){//有读事件
	    caddr_len=sizeof(caddr);
            connfd=accept(listenfd,(struct sockaddr*)&caddr,&caddr_len);//有连接	   
	    tempevent.data.fd=connfd;
	    tempevent.events=EPOLLIN;
            epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&tempevent);
	 }else{            
	    sockfd=ArrEvents[i].data.fd;
            n=read(sockfd,buf,sizeof(buf));
	    if(n==-1){
               sys_error("read is error");
	    }
	    if(n==0){
	       epoll_ctl(epfd,EPOLL_CTL_DEL,sockfd,NULL);      
               close(sockfd);
	    }
            for(j=0;j<nums;j++){
               buf[j]=toupper(buf[j]);    
	    }
	    write(sockfd,buf,n);
	    write(STDOUT_FILENO,buf,n);
	 }
      }
   }
   close(listenfd);
   return 0;
}
